package com.ht.api.callback.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.ht.api.callback.CallbackFunction;
import com.ht.api.constant.CacheConstants;
import com.ht.api.db.Db;
import com.ht.api.db.DbConfig;
import com.ht.api.db.Entity;
import com.ht.api.db.util.RedisUtil;
import com.ht.api.wwx.WXChatUtil;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 产生会话回调事件
 * @author asq
 * @createTime 2025年1月17日 13:26:47
 */
@Slf4j
public class WwxMsgauditNotifyCallbackFunction implements CallbackFunction{
	
	@Override
	public void execute(String appid, Entity callback, JSONObject params) {
		// 获取缓存中的存档消息序号
		long tenantId = getTenantId(appid);
		String key = getKey(tenantId, appid);
		Integer seq = RedisUtil.get(key);
		seq = seq == null ? 0 : seq;
		log.info("[会话存档sdk]会话回调事件，上次seq：{}", seq);
		
		// 拉取会话存档
		String msgList = WXChatUtil.queryChatMsgList(seq);
		log.info("[会话存档sdk]拉取会话存档：{}", msgList);
		
		// 解析出会话列表，
		JSONObject json = JSONUtil.parseObj(msgList);
		JSONArray chatdata = json.getJSONArray("chatdata");
		List<String> messageList = new ArrayList<>();
		for (int i = 0; i < chatdata.size(); i++) {
			JSONObject chat = chatdata.getJSONObject(i);
			seq = chat.getInt("seq");
			
			// 只处理公钥版本为2的加密数据，因为公钥版本为1的，已经找不到私钥了，无法解密
			int publickeyVer = chat.getInt("publickey_ver");
			if (publickeyVer == 2) {
				String encryptRandomKey = chat.getStr("encrypt_random_key");
				String encryptChatMsg = chat.getStr("encrypt_chat_msg");
				
				// 解密消息
				String message = WXChatUtil.decryptChatMsg(encryptRandomKey, encryptChatMsg);
				messageList.add(message);
				log.info("[会话存档sdk]会话回调事件，解密消息，公钥版本：{}，seq:{}，msg:{}", publickeyVer, seq, message);
			} else {
				log.info("[会话存档sdk]会话回调事件，无法解密的数据，公钥版本：{}，seq:{}", publickeyVer, seq);
			}
		}
		
		// 保存数据库
		saveMessage(appid, tenantId, messageList);
		
		// 更新缓存中的seq
		RedisUtil.set(key, seq);
	}

	/**
	 * 保存解密后的消息到数据库
	 * @param appid
	 * @param tenantId
	 * @param messageList
	 */
	private void saveMessage(String appid, long tenantId, List<String> messageList) {
		List<Entity> datalist = new ArrayList<>();
		messageList.stream().forEach(message -> {
			// 解析消息为json对象
			JSONObject msg = JSONUtil.parseObj(message);
			String msgType = msg.getStr("msgtype");
			String msgtime = DateUtil.formatDateTime(new Date(msg.getLong("msgtime")));
			JSONArray tolist = msg.getJSONArray("tolist");
			
			// 获取接收方列表的hash值
			String tolist_hash = tolist.stream().map(s -> String.valueOf(Math.abs(s.hashCode())))
					.collect(Collectors.joining(","));
			
			// 保存数据库
			Entity wx_msg = Db.createEntity("wx_msg");
			wx_msg.set("appid", appid);
			wx_msg.set("isroom", StrUtil.isBlank(msg.getStr("roomid")) ? 0 : 1);
			wx_msg.set("tolist_hash", tolist_hash);
			wx_msg.set("msgid", msg.getStr("msgid"));
			wx_msg.set("action", msg.getStr("action"));
			wx_msg.set("from", msg.getStr("from"));
			wx_msg.set("tolist", tolist.toString());
			wx_msg.set("roomid", msg.getStr("roomid"));
			wx_msg.set("msgtime", msgtime);
			wx_msg.set("msgtype", msgType);
			wx_msg.set("content", msg.getJSONObject(msgType).toString());
			if (tolist.size() == 1) {
				wx_msg.set("touser", tolist.get(0));
			}
			datalist.add(wx_msg);
		});
		Db.insertBatchWithStream(DbConfig.useTenantSLC(tenantId), datalist);
	}
	
	/**
	 * 获取租户的缓存中的存档消息序号的key
	 * @param tenantId 租户ID
	 * @param appid 应用ID
	 * @return
	 */
	private String getKey(long tenantId, String appid) {
		return String.format("%s:%s:seq", tenantId, appid);
	}

	/**
	 * 返回应用对应的租户ID
	 * @param appId 应用ID
	 * @return
	 */
	private long getTenantId(String appId) {
		Entity entity = RedisUtil.get(CacheConstants.KEY_APP + appId);
		return entity.getLong("tenant_id");
	}
}
